home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume15 / upm / part01 next >
Encoding:
Text File  |  1990-12-17  |  49.8 KB  |  2,373 lines

  1. Newsgroups: comp.sources.misc
  2. X-UNIX-From: mrapple@quack.sac.ca.us
  3. organization: The Duck Pond, Stockton, CA
  4. summary: This is sort of a beta release.
  5. subject: v15i101: Z-80 emulator in C, with CP/M BIOS (part 1/2)
  6. from: mrapple@quack.sac.ca.us (Nick Sayer)
  7. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  8.  
  9. Posting-number: Volume 15, Issue 101
  10. Submitted-by: mrapple@quack.sac.ca.us (Nick Sayer)
  11. Archive-name: upm/part01
  12.  
  13. #!/bin/sh
  14. # This is a shell archive (shar 3.24)
  15. # made 10/31/1990 19:28 UTC by mrapple@quack
  16. # Source directory /files/users/mrapple/upm
  17. #
  18. # existing files WILL be overwritten
  19. #
  20. # This is part 1 of a multipart archive                                    
  21. # do not concatenate these parts, unpack them in order with /bin/sh        
  22. #
  23. # This shar contains:
  24. # length  mode       name
  25. # ------ ---------- ------------------------------------------
  26. #    853 -rw-r--r-- Makefile
  27. #    717 -rw-r--r-- README
  28. #   1625 -rw-r--r-- README.upm
  29. #   5553 -rw-r--r-- bios.c
  30. #   8597 -rw-r--r-- debug.c
  31. #    462 -rw-r--r-- io_ask.c
  32. #    255 -rw-r--r-- io_mem.c
  33. #    373 -rw-r--r-- lh.c
  34. #   1262 -rw-r--r-- loadhex.c
  35. #   1062 -rw-r--r-- makedrive.c
  36. #   9809 -rw-r--r-- udbg.c
  37. #   6850 -rw-r--r-- upm.c
  38. #   1744 -rw-r--r-- upm.h
  39. #  27243 -rw-r--r-- z80.c
  40. #   1672 -rw-r--r-- z80.h
  41. #  16492 -rw-r--r-- z80_cbed.c
  42. #
  43. if touch 2>&1 | fgrep '[-amc]' > /dev/null
  44.  then TOUCH=touch
  45.  else TOUCH=true
  46. fi
  47. if test -r shar3_seq_.tmp; then
  48.     echo "Must unpack archives in sequence!"
  49.     next=`cat shar3_seq_.tmp`; echo "Please unpack part $next next"
  50.     exit 1
  51. fi
  52. # ============= Makefile ==============
  53. echo "x - extracting Makefile (Text)"
  54. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  55. Xz80.o: z80.h
  56. Xz80_cbed.o: z80.h
  57. X
  58. XZOBJS = z80.o z80_cbed.o
  59. XIFILES = z80.h
  60. X
  61. XCFLAGS = -O
  62. X
  63. Xall: upm debug dumbrun makedrive dbg
  64. X
  65. Xdebug: $(ZOBJS) io_ask.o debug.o loadhex.o
  66. X    $(CC) $(CFLAGS) $(ZOBJS) io_ask.o debug.o loadhex.o -o debug
  67. X
  68. Xdbg: $(ZOBJS) io_ask.o dbg.o loadhex.o
  69. X    $(CC) $(CFLAGS) $(ZOBJS) io_ask.o dbg.o loadhex.o -o dbg
  70. X
  71. Xdumbrun: $(ZOBJS) io_ask.o dumbrun.o
  72. X    $(CC) $(CFLAGS) $(ZOBJS) io_ask.o dumbrun.o -o dumbrun
  73. X
  74. Xbios.o: z80.h
  75. Xdebug.o: z80.h
  76. Xio_ask.o: z80.h
  77. Xio_mem.o: z80.h
  78. Xloadhex.o: z80.h
  79. Xlh.o: z80.h
  80. Xudbg.o: z80.h
  81. X
  82. Xupm: $(ZOBJS) io_mem.o upm.o loadhex.o bios.o udbg.o
  83. X    $(CC) $(CFLAGS) $(ZOBJS) io_mem.o upm.o loadhex.o bios.o udbg.o -o upm
  84. X
  85. Xmakedrive: makedrive.c
  86. X    $(CC) $(CFLAGS) makedrive.c -o makedrive
  87. X
  88. Xinitdisk: initdisk.c
  89. X    $(CC) $(CFLAGS) initdisk.c -o initdisk
  90. X
  91. X$(ZOBJS): z80.h
  92. X
  93. Xclean:
  94. X    rm -f upm debug dumbrun makedrive initdisk *.o
  95. SHAR_EOF
  96. $TOUCH -am 0928182190 Makefile &&
  97. chmod 0644 Makefile ||
  98. echo "restore of Makefile failed"
  99. set `wc -c Makefile`;Wc_c=$1
  100. if test "$Wc_c" != "853"; then
  101.     echo original size 853, current size $Wc_c
  102. fi
  103. # ============= README ==============
  104. echo "x - extracting README (Text)"
  105. sed 's/^X//' << 'SHAR_EOF' > README &&
  106. XSince emulating a CPU is a fairly memory intensive thing to do,
  107. Xit's unlikely that the Z-80 emulator code will require any reworking
  108. Xto fit your needs. There is an option you need to set, though. Two
  109. Xfiles are included to handle I/O instructions. io_mem.c implements
  110. Xa 256 byte RAM on the I/O space. io_ask.c prompts the console
  111. Xfor input and prints output writes.
  112. X
  113. XYou also have a couple choices for main():
  114. X
  115. Xdebug.c is a debugger. This debugger is intended primarily to debug
  116. Xthe interpreter itself rather than debug z-80 code.
  117. X
  118. Xupm.c implements CP/M on top of the emulator. See README.upm
  119. X
  120. XMany thanks to Mark W. Eichin for his help in debugging some
  121. Xof my truely nasty code during Alpha-testing. Truely a saint.
  122. X
  123. SHAR_EOF
  124. $TOUCH -am 1031111990 README &&
  125. chmod 0644 README ||
  126. echo "restore of README failed"
  127. set `wc -c README`;Wc_c=$1
  128. if test "$Wc_c" != "717"; then
  129.     echo original size 717, current size $Wc_c
  130. fi
  131. # ============= README.upm ==============
  132. echo "x - extracting README.upm (Text)"
  133. sed 's/^X//' << 'SHAR_EOF' > README.upm &&
  134. XThe BIOS is implemented like this:
  135. X
  136. Xxx00: 76 C9 00 76 C9 00 76 C9 00......
  137. X
  138. XFor the non-z80-literate, that is a series of HALT and RETurn from
  139. Xsubroutine statements. HALT instructions return control to the calling
  140. X(c program) routine that started the Z-80 running in the first place.
  141. XBy dividing the low 8 bits of the PC by 3, we can find out what BIOS
  142. Xroutine the caller wanted, do it in C, then return.
  143. X
  144. Xupm takes various paramaters either on the command line or in
  145. X~/.upmrc. If specified, command line paramaters take precedence over
  146. X.upmrc options. Options are in the form of dev:file, where dev is
  147. XA-O, for disk devices, or TY, LP, PT, U1 or U2, for alternate physical
  148. Xdevices. The files specified are attached to the coresponding disks or
  149. Xphysical devices. The above identifiers corespond to these CP/M physical
  150. Xdevices:
  151. X
  152. XTY    TTY:
  153. XLP    LPT:
  154. XPT    PTP: PTR:
  155. XU1    UC1: UL1: UP1: UR1:
  156. XU2    UP2: UR2:
  157. X
  158. XThe CRT: device is permanently assigned to stdin/stdout. stdin/stdout
  159. Xare set to RAW mode, to make all keys work. The last BIOS jump table
  160. Xentry is non-standard, and causes the CP/M system to halt and control
  161. Xreturn to unix. The CP/M program EXIT.COM will do this.
  162. X
  163. XAs usual, the BAT: device is a combination of CRT: and LPT:
  164. X
  165. XThe default I/O byte assigns as follows:
  166. X
  167. XCON:=CRT:
  168. XRDR:=PTP:
  169. XPUN:=PTR:
  170. XLST:=LPT:
  171. X
  172. XA typical command line might say:
  173. X
  174. X% upm a:cpm.adrive lp:printer_file pt:copy_file
  175. X
  176. XThe device identifiers may be in upper-case, but the files, of course,
  177. Xwill be literal-cased.
  178. X
  179. XAll device files except LP: will be fopen()ed "r+". LP: will be
  180. Xfopen()ed "w".
  181. X
  182. XAny device not specifically assigned will act like /dev/null.
  183. SHAR_EOF
  184. $TOUCH -am 1031112690 README.upm &&
  185. chmod 0644 README.upm ||
  186. echo "restore of README.upm failed"
  187. set `wc -c README.upm`;Wc_c=$1
  188. if test "$Wc_c" != "1625"; then
  189.     echo original size 1625, current size $Wc_c
  190. fi
  191. # ============= bios.c ==============
  192. echo "x - extracting bios.c (Text)"
  193. sed 's/^X//' << 'SHAR_EOF' > bios.c &&
  194. X/*
  195. X
  196. Xbios.c - CP/M BIOS in C
  197. X
  198. X(C) MCMXM - Nick Sayer - All rights reserved.
  199. X
  200. XSee COPYRIGHT file for more details.
  201. X
  202. X*/
  203. X
  204. X#include <stdio.h>
  205. X#include "z80.h"
  206. X#include "upm.h"
  207. X
  208. X#include <sys/ioctl.h>
  209. X
  210. X#define IO_BYTE 3
  211. X
  212. XWORD trk,sec,dma,dsk;
  213. X
  214. Xchar cold_flag=0;
  215. X
  216. X/*
  217. X
  218. XOur Z-80 BIOS is just HALT, RET, NOP, HALT, RET, NOP..... We find out
  219. Xwhich BIOS jump it is by dividing the LSB of PC by 3.
  220. X
  221. XTHIS PRESUMES BIOS BEGINS ON AN EVEN PAGE BOUNDARY. This is a pretty
  222. Xgood assumption.
  223. X
  224. XBIOS Memory map:
  225. X
  226. X0000 -     jump table
  227. X0080 -     DIRBUF
  228. X0100 -     disk buffers - this set up in upm.c
  229. X
  230. XIt is up to upm.c to set up the disk buffers as necessary for
  231. Xdifferent size devices, and set up the pointers in diskbufs[].
  232. X
  233. X*/
  234. X
  235. Xchar bios()
  236. X{
  237. X  register char bios_call;
  238. X
  239. X  bios_call=(PC&0xff)/3;
  240. X  PC++; /* Skip past the HALT */
  241. X
  242. Xif(debugflag) printf("\tBios! - %d from %x\n\r",bios_call,PC);
  243. X
  244. X  switch(bios_call)
  245. X  {
  246. X    case 0:cold_boot(); /* DON'T break... we WANT to fall into warm boot! */
  247. X    case 1:warm_boot();
  248. X    break;
  249. X    case 2:stat_con();
  250. X    break;
  251. X    case 3:read_con();
  252. X    break;
  253. X    case 4:write_con();
  254. X    break;
  255. X    case 5:write_lst();
  256. X    break;
  257. X    case 6:write_pun();
  258. X    break;
  259. X    case 7:read_rdr();
  260. X    break;
  261. X    case 8:home_dsk();
  262. X    break;
  263. X    case 9:sel_dsk();
  264. X    break;
  265. X    case 10:set_trk();
  266. X    break;
  267. X    case 11:set_sec();
  268. X    break;
  269. X    case 12:set_dma();
  270. X    break;
  271. X    case 13:read_dsk();
  272. X    break;
  273. X    case 14:write_dsk();
  274. X    break;
  275. X    case 15:stat_lst();
  276. X    break;
  277. X    case 16:sec_trans();
  278. X    break;
  279. X    case 30:shell_escape();
  280. X    break;
  281. X    case 31:quit(); return 1;
  282. X    default:
  283. X    printf("unhandled bios call %d\n\r",bios_call);
  284. X    debugit();
  285. X  }
  286. X
  287. X  return 0;
  288. X}
  289. X
  290. Xquit()
  291. X{
  292. X}
  293. X
  294. Xshell_escape()
  295. X{
  296. X    debugit();
  297. X}
  298. X
  299. Xcold_boot()
  300. X{
  301. X
  302. X  real_z80_mem[IO_BYTE]=0x95; /* CRT, PUN, RDR, LPT */
  303. X  real_z80_mem[0]=0xC3;
  304. X  real_z80_mem[1]=0x03;
  305. X  real_z80_mem[2]=(ccp_start>>8)+8+0xe; /* First page of BIOS */
  306. X  real_z80_mem[5]=0xC3;
  307. X  real_z80_mem[6]=0x06;
  308. X  real_z80_mem[7]=(ccp_start>>8)+8; /* First page of BDOS */
  309. X  printf("\n\r\n\rCP/M Ver 2.2\n\rCopyright Digital Research, Inc.\n\r");
  310. X  printf("UP/M Version 1.0B\n\rCopyright Nick Sayer\n\r\n\r");
  311. X  cold_flag++;
  312. X
  313. X}
  314. X
  315. Xwarm_boot()
  316. X{
  317. X  register WORD i;
  318. X
  319. X  for(i=0;i<SIZE_CCP_IMAGE;i++)
  320. X    real_z80_mem[i+ccp_start]=ccp_image[i];
  321. X
  322. X  if (cold_flag)
  323. X  {
  324. X    cold_flag=0;
  325. X    PC=ccp_start;
  326. X  }
  327. X  else
  328. X    PC=ccp_start+3;
  329. X
  330. X  BC=0;
  331. X  debugit();
  332. X}
  333. X
  334. Xstat_con()
  335. X{
  336. X  FILE *which;
  337. X  int ret;
  338. X
  339. X  switch (real_z80_mem[IO_BYTE]&0x3)
  340. X  {
  341. X    case 0:which=devices[F_TY]; break;
  342. X    case 1:which=stdin; break;
  343. X    case 2:which=stdin; break;
  344. X    case 3:which=devices[F_U1]; break;
  345. X  }
  346. X
  347. X  ioctl(fileno(which),FIONREAD,&ret);
  348. X  AF=(AF&0xff)|(ret?0xff00:0);
  349. X/* */
  350. X/*  if(!ret) AF |= FLAG_Z; else AF &= ~FLAG_Z; */
  351. X  AF |= FLAG_Z;
  352. X
  353. X}
  354. X
  355. Xread_con()
  356. X{
  357. X  FILE *which;
  358. X
  359. X  switch (real_z80_mem[IO_BYTE]&0x3)
  360. X  {
  361. X    case 0:which=devices[F_TY]; break;
  362. X    case 1:which=stdin; break;
  363. X    case 2:which=stdin; break;
  364. X    case 3:which=devices[F_U1]; break;
  365. X  }
  366. X  if (which==NULL)
  367. X  {
  368. X    AF&=0xff;
  369. X    return;
  370. X  }
  371. X  AF=(AF&0xff)|(getc(which)<<8);
  372. X}
  373. X
  374. Xwrite_con()
  375. X{
  376. X  FILE *which;
  377. X
  378. X  switch(real_z80_mem[IO_BYTE]&0x3)
  379. X  {
  380. X    case 0:which=devices[F_TY]; break;
  381. X    case 1:which=stdout; break;
  382. X    case 2:write_lst(); which=stdout; break;
  383. X    case 3:which=devices[F_U1]; break;
  384. X  }
  385. X  if (which!=NULL)
  386. X    putc(BC&0xff,which);
  387. X}
  388. X
  389. Xstat_lst()
  390. X{
  391. X  FILE *which;
  392. X
  393. X/*
  394. X  switch((real_z80_mem[IO_BYTE]>>6)&0x3)
  395. X  {
  396. X    case 0:which=devices[F_TY]; break;
  397. X    case 1:which=stdout; break;
  398. X    case 2:which=devices[F_LP]; break;
  399. X    case 3:which=devices[F_U1]; break;
  400. X  }
  401. X
  402. XUnder unix, writing is always fine.
  403. X
  404. X*/
  405. X  AF|=0xff00;
  406. X}
  407. X
  408. Xwrite_lst()
  409. X{
  410. X  FILE *which;
  411. X
  412. X  switch((real_z80_mem[IO_BYTE]>>6)&0x3)
  413. X  {
  414. X    case 0:which=devices[F_TY]; break;
  415. X    case 1:which=stdout; break;
  416. X    case 2:which=devices[F_LP]; break;
  417. X    case 3:which=devices[F_U1]; break;
  418. X  }
  419. X  if (which!=NULL)
  420. X    putc(BC&0xff,which);
  421. X}
  422. X
  423. Xwrite_pun()
  424. X{
  425. X  FILE *which;
  426. X
  427. X  switch((real_z80_mem[IO_BYTE]>>4)&0x3)
  428. X  {
  429. X    case 0:which=devices[F_TY]; break;
  430. X    case 1:which=devices[F_PT]; break;
  431. X    case 2:which=devices[F_U1]; break;
  432. X    case 3:which=devices[F_U2]; break;
  433. X  }
  434. X  if (which!=NULL)
  435. X    putc(BC&0xff,which);
  436. X}
  437. X
  438. Xread_rdr()
  439. X{
  440. X  FILE *which;
  441. X
  442. X  switch((real_z80_mem[IO_BYTE]>>2)&0x3)
  443. X  {
  444. X    case 0:which=devices[F_TY]; break;
  445. X    case 1:which=devices[F_PT]; break;
  446. X    case 2:which=devices[F_U1]; break;
  447. X    case 3:which=devices[F_U2]; break;
  448. X  }
  449. X  if (which==NULL)
  450. X  {
  451. X    AF&=0xff;
  452. X    return;
  453. X  }
  454. X  AF=(AF&0xff)|(getc(which)<<8);
  455. X}
  456. X
  457. Xhome_dsk()
  458. X{
  459. X  bioslog("home disk\n\r");
  460. X  trk = 0;
  461. X}
  462. X
  463. Xsec_trans()
  464. X{
  465. X  bioslog("set trans to 0x%04x\n\r",BC);
  466. X  HL=BC;
  467. X}
  468. X
  469. Xsel_dsk()
  470. X{
  471. X  if (disks[BC&0xf]==NULL)
  472. X  {
  473. X    HL=0;
  474. X    bioslog("Invalid disk select 0x%04x\n\r",BC);
  475. X  }
  476. X  else
  477. X  {
  478. X    HL=diskbufs[BC&0xf];
  479. X    dsk=BC&0xf;
  480. X    bioslog("Valid disk select [%x] 0x%4x\n\r",BC&0xf,HL);
  481. X  }
  482. X}
  483. X
  484. Xset_trk()
  485. X{
  486. X  bioslog("set track to 0x%02x\n\r",BC&0xff);
  487. X  trk=BC&0xff;
  488. X}
  489. X
  490. Xset_sec()
  491. X{
  492. X  bioslog("set sec to 0x%02x\n\r",BC&0xff);
  493. X  sec=BC&0xff;
  494. X}
  495. X
  496. Xset_dma()
  497. X{
  498. X  bioslog("set dma to 0x%04x\n\r",BC);
  499. X  dma=BC;
  500. X}
  501. X
  502. Xread_dsk()
  503. X{
  504. X  bioslog("Reading: track %d, sec %d, offset %d, dma 0x%4x\n\r",
  505. X     trk, sec, 128*((trk*0x40)+sec), dma);
  506. X  fseek(disks[dsk],128*((trk*0x40)+sec),0);
  507. X  AF=(AF&0xff)|((fread(real_z80_mem+dma,128,1,disks[dsk])!=1)<<8);
  508. X}
  509. X
  510. Xwrite_dsk()
  511. X{
  512. X  bioslog("Writing: track %d, sec %d, offset %d, dma 0x%4x\n\r",
  513. X     trk, sec, 128*((trk*0x40)+sec), dma);
  514. X  fseek(disks[dsk],128*((trk*0x40)+sec),0);
  515. X  AF=(AF&0xff)|((fwrite(real_z80_mem+dma,128,1,disks[dsk])!=1)<<8);
  516. X}
  517. SHAR_EOF
  518. $TOUCH -am 0928182090 bios.c &&
  519. chmod 0644 bios.c ||
  520. echo "restore of bios.c failed"
  521. set `wc -c bios.c`;Wc_c=$1
  522. if test "$Wc_c" != "5553"; then
  523.     echo original size 5553, current size $Wc_c
  524. fi
  525. # ============= debug.c ==============
  526. echo "x - extracting debug.c (Text)"
  527. sed 's/^X//' << 'SHAR_EOF' > debug.c &&
  528. X/*
  529. X
  530. Xdebug.c - debugger for z-80 emulator.
  531. X
  532. X*/
  533. X
  534. X#include <stdio.h>
  535. X#include <setjmp.h>
  536. X#include <signal.h>
  537. X
  538. X#include "z80.h"
  539. Xextern char *sys_errlist[];
  540. Xextern int errno;
  541. X
  542. Xjmp_buf lj;
  543. X
  544. Xvoid int_handler()
  545. X{
  546. X  longjmp(lj);
  547. X}
  548. X
  549. Xlong z80_memlines[65536];
  550. Xlong z80_memseeks[65536];
  551. XFILE *z80_file;
  552. X
  553. X
  554. X
  555. Xmain()
  556. X{
  557. X  int i;
  558. X
  559. X  setjmp(lj);
  560. X  signal(SIGINT,int_handler);
  561. X
  562. X  z80_file = 0;
  563. X  while(1)
  564. X  {
  565. X    char ibuf[128], *istat;
  566. X    
  567. X    char cmd_char;
  568. X
  569. X    do {
  570. X      printf("\n>");
  571. X      bzero(ibuf,127);
  572. X      istat = fgets(ibuf, 127, stdin);
  573. X    } while (istat && strlen(ibuf)<2);
  574. X    if(!istat) break;
  575. X    
  576. X    cmd_char = ibuf[0];
  577. X    switch(cmd_char)
  578. X    {
  579. X    case 'd':dump(ibuf);
  580. X    break;
  581. X    case 's':z80_instr(ibuf);
  582. X    break;
  583. X    case 'g':z80_run(ibuf);
  584. X    break;
  585. X    case 'c':pr_reg(ibuf);
  586. X    break;
  587. X    case 'l':gethex(ibuf);
  588. X    break;
  589. X    case 'b':getbin(ibuf);
  590. X    break;
  591. X    case 'm':movemem(ibuf);
  592. X    break;
  593. X    case 'w':writehex(ibuf);
  594. X    break;
  595. X    case 'y':getlines(ibuf);
  596. X    break;
  597. X    case 'r':set_reg(ibuf);
  598. X    break;
  599. X    case 'q':exit(0);
  600. X    break;
  601. X    case 'e':edit(ibuf);
  602. X    break;
  603. X    case '$':user_cmd(ibuf);
  604. X    break;
  605. X    default:help(ibuf);
  606. X    break;
  607. X    }
  608. X  }
  609. X
  610. X}
  611. X
  612. X/*
  613. X
  614. Xon-line help
  615. X
  616. X*/
  617. X
  618. Xhelp(ibuf) char* ibuf;
  619. X{
  620. X  printf("\nb file           - load a binary image\n");
  621. X  printf("c                - display register values\n");
  622. X  printf("d start [len]    - display memory\n");
  623. X  printf("e start          - edit memory\n");
  624. X  printf("g                - start Z-80 running\n");
  625. X  printf("l file           - load hex file\n");
  626. X  printf("m start end dest - move a chunk of memory\n");
  627. X  printf("q                - quit\n");
  628. X  printf("r reg val        - change register/flag value\n");
  629. X  printf("s                - single step\n");
  630. X  printf("w start end file - write hex file\n");
  631. X  printf("y file           - read lines file\n");
  632. X  printf("$                - execute user command\n");
  633. X}
  634. X
  635. X/*
  636. X
  637. Xdump
  638. X
  639. X*/
  640. X
  641. Xdump(ibuf) char* ibuf;
  642. X{
  643. X  int start,end=0;
  644. X
  645. X  if(2!=sscanf(ibuf,"%*s %x %x",&start,&end)) {
  646. X    printf("usage: dump start end\n");
  647. X    return;
  648. X  }
  649. X  pr_mem(start,end);
  650. X}
  651. X
  652. X/*
  653. X
  654. Xedit
  655. X
  656. X*/
  657. X
  658. Xedit(ibuf) char* ibuf;
  659. X{
  660. X  int start,byte;
  661. X  if(2!=sscanf(ibuf,"%*s %x %x",&start,&byte)) {
  662. X    printf("usage: edit address value\n");
  663. X    return;
  664. X  }
  665. X  start&=0xffff;
  666. X  byte&=0xff;
  667. X  real_z80_mem[start]=byte;
  668. X}
  669. X
  670. X/*
  671. X
  672. Xset registers
  673. X
  674. X*/
  675. X
  676. Xset_reg(ibuf) char* ibuf;
  677. X{
  678. X  char reg[80];
  679. X  int i;
  680. X  if(2!=sscanf(ibuf,"%*s %s %x",reg, &i)) {
  681. X    printf("usage: set register value\n");
  682. X    return;
  683. X  }
  684. X  i&=0xffff;
  685. X  if (!strcmp(reg,"pc"))
  686. X    PC=i;
  687. X  else if (!strcmp(reg,"sp"))
  688. X    SP=i;
  689. X  else if (!strcmp(reg,"af"))
  690. X    AF=i;
  691. X  else if (!strcmp(reg,"bc"))
  692. X    BC=i;
  693. X  else if (!strcmp(reg,"de"))
  694. X    DE=i;
  695. X  else if (!strcmp(reg,"hl"))
  696. X    HL=i;
  697. X  else if (!strcmp(reg,"af'"))
  698. X    AF2=i;
  699. X  else if (!strcmp(reg,"bc'"))
  700. X    BC2=i;
  701. X  else if (!strcmp(reg,"de'"))
  702. X    DE2=i;
  703. X  else if (!strcmp(reg,"hl'"))
  704. X    HL2=i;
  705. X  else if (!strcmp(reg,"ix"))
  706. X    IX=i;
  707. X  else if (!strcmp(reg,"iy"))
  708. X    IY=i;
  709. X  else if (!strcmp(reg,"i"))
  710. X    IR=(IR&0xff)|(i<<8);
  711. X  else if (!strcmp(reg,"r"))
  712. X    IR=(IR&0xff00)|i;
  713. X  else {
  714. X    printf("register should be one of: pc sp af bc de hl af' bc' de' hl' ix iy i r\n");
  715. X  }
  716. X}
  717. X
  718. X/*
  719. X
  720. Xdump out memory for the user. A is the starting address. L is the amount
  721. Xof dumping he wants. if L is 0, a default value is supplied.
  722. X
  723. X*/
  724. X
  725. Xpr_mem(a,l)
  726. XWORD a,l;
  727. X{
  728. X  WORD i;
  729. X  int counter=0;
  730. X
  731. X  if (!l)
  732. X    l=0x100;
  733. X  for(i=0;i<l;i++)
  734. X  {
  735. X    if (!(counter%16))
  736. X      printf("%04X- ",(a+i)&0xffff);
  737. X
  738. X    printf("%02X ",real_z80_mem[(a+i)&0xffff]);
  739. X    counter++;
  740. X
  741. X    if (!(counter%16))
  742. X    {
  743. X      char c,j;
  744. X      for (j=15;j>=0;j--)
  745. X      {
  746. X    c=real_z80_mem[(a+i-j)&0xffff]&0x7f;
  747. X        putchar( ((c>0x20) && (c<0x7f))?c:'.' );
  748. X      }
  749. X      printf("\n");
  750. X    }
  751. X  }
  752. X  if (counter%16)
  753. X  {
  754. X    int j;
  755. X    char c;
  756. X    for(j=counter%16;j>0;j--)
  757. X    {
  758. X      c=real_z80_mem[(a+i-j)&0xffff]&0x7f;
  759. X      putchar( ((c>0x20) && (c<0x7f))?c:'.' );
  760. X    }
  761. X    printf("\n");
  762. X  }
  763. X}
  764. X
  765. Xshow_debug_line(addr) WORD addr;
  766. X{
  767. X  char ibuf[1024];
  768. X  int ilow = addr, ihi = addr;
  769. X  if(z80_file) {
  770. X    while(ilow>0 && !z80_memlines[ilow]) ilow--;
  771. X    while(ihi<65536 && !z80_memlines[ilow]) ihi++;
  772. X    printf("(range %d %d)\n",ilow,ihi);
  773. X    fseek(z80_file,z80_memseeks[ilow],0);
  774. X    fgets(ibuf,1023,z80_file);
  775. X    printf("%d: %s",z80_memlines[ilow],ibuf); /* \n included in ibuf... */
  776. X  }
  777. X}
  778. X
  779. Xpr_reg(ibuf) char* ibuf;
  780. X{
  781. X  static char *flag_chars="CNVxHxZS";
  782. X  int i;
  783. X
  784. X  printf("\nA =%02XH BC =%04XH DE =%04XH HL =%04XH SP=%04XH IX=%04XH\n"
  785. X      ,AF>>8,BC,DE,HL,SP,IX);
  786. X  printf("A'=%02XH BC'=%04XH DE'=%04XH HL'=%04XH PC=%04XH IY=%04XH\n"
  787. X      ,AF2>>8,BC2,DE2,HL2,PC,IY);
  788. X
  789. X  printf("\nI=%02XH R=%02XH  F=",IR>>8,IR%0xff);
  790. X  for(i=7;i>=0;i--)
  791. X    putchar( (AF&(1<<i))?flag_chars[i]:'-' );
  792. X  printf(" F'=");
  793. X  for(i=7;i>=0;i--)
  794. X    putchar( (AF2&(1<<i))?flag_chars[i]:'-' );
  795. X  printf("  IFF1=%c  IFF2=%c"
  796. X      ,(INT_FLAGS&IFF1)?'1':'-',(INT_FLAGS&IFF2)?'1':'-');
  797. X
  798. X  printf("\n(PC)=");
  799. X  for(i=PC; i<PC+16; i++) {
  800. X    printf("%02X ",real_z80_mem[i]);
  801. X  }
  802. X  printf("\n(HL)=");
  803. X  for(i=HL; i<HL+16; i++) {
  804. X    printf("%02X ",real_z80_mem[i]);
  805. X  }
  806. X  printf("\n");
  807. X
  808. X  show_debug_line(PC);
  809. X}
  810. X
  811. Xgetlines(ibuf) char* ibuf;
  812. X{
  813. X  char fname[80];
  814. X  char lbuf[1024], *lstat;
  815. X
  816. X  if(z80_file) {
  817. X    int i;
  818. X    fclose(z80_file);
  819. X    for(i = 0; i<65536; i++) {
  820. X      z80_memlines[i] = 0;
  821. X      z80_memseeks[i] = 0;
  822. X    }
  823. X  }
  824. X  sscanf(ibuf,"%*s %s",fname);
  825. X
  826. X  z80_file=fopen(fname,"r");
  827. X  if (z80_file==NULL)
  828. X  {
  829. X    printf("%s: %s",fname,sys_errlist[errno]);
  830. X    return;
  831. X  }
  832. X  /* long z80_memlines[65536]; */
  833. X  do {
  834. X    int addr, line, told;
  835. X    told = ftell(z80_file);
  836. X    lstat = fgets(lbuf, 1023, z80_file);
  837. X    if(!lstat) break;
  838. X    sscanf(lbuf,"%d: %x",&line,&addr);
  839. X    z80_memlines[addr] = line;
  840. X    z80_memseeks[addr] = told;
  841. X  } while(lstat);
  842. X
  843. X  /* fclose(file); */
  844. X}
  845. X
  846. X
  847. Xgethex(ibuf) char* ibuf;
  848. X{
  849. X  char fname[80];
  850. X  FILE *file;
  851. X
  852. X  sscanf(ibuf,"%*s %s",fname);
  853. X
  854. X  file=fopen(fname,"r");
  855. X  if (file==NULL)
  856. X  {
  857. X    printf("%s: %s",fname,sys_errlist[errno]);
  858. X    return;
  859. X  }
  860. X  loadhex(file);
  861. X  fclose(file);
  862. X}
  863. X
  864. Xgetbin(ibuf) char* ibuf;
  865. X{
  866. X  char fname[80];
  867. X  FILE *file;
  868. X  WORD count=0;
  869. X
  870. X  sscanf(ibuf,"%*s %s",fname);
  871. X
  872. X  file=fopen(fname,"r");
  873. X  if (file==NULL)
  874. X  {
  875. X    printf("%s: %s",fname,sys_errlist[errno]);
  876. X    return;
  877. X  }
  878. X  while (!feof(file))
  879. X    real_z80_mem[count++]=getc(file);
  880. X  fclose(file);
  881. X}
  882. X
  883. Xextern BYTE csum();
  884. X/*
  885. X#define HEXCHAR(a) ( ((a)>=10) ? ((a)+'a'-10) : ((a)+'0') )
  886. X*/
  887. Xchar HEXCHAR(a)
  888. Xchar a;
  889. X{
  890. X  return ( ((a)>=10) ? ((a)+'a'-10) : ((a)+'0') );
  891. X}
  892. Xwritehex(ibuf) char* ibuf;
  893. X{
  894. X  char fname[80],c[80];
  895. X  FILE *file;
  896. X  WORD start,end,i,j;
  897. X  BYTE tmp;
  898. X  char counter=0;
  899. X
  900. X  if(3!=sscanf(ibuf,"%*s %hx %hx %s",&start,&end,fname)) {
  901. X    printf("usage: write start end filename\n");
  902. X    return;
  903. X  }
  904. X  end++;
  905. X
  906. X  file=fopen(fname,"a");
  907. X  if (file==NULL)
  908. X  {
  909. X    printf("%s: %s",fname,sys_errlist[errno]);
  910. X    return;
  911. X  }
  912. X  for(i=start;i<=end-32;i+=32)
  913. X  {
  914. X    strcpy(c,":20");
  915. X    c[3]=HEXCHAR(i>>12);
  916. X    c[4]=HEXCHAR((i>>8)&15);
  917. X    c[5]=HEXCHAR((i>>4)&15);
  918. X    c[6]=HEXCHAR(i&15);
  919. X    c[7]='0';
  920. X    c[8]='0';
  921. X    for(j=0;j<32;j++)
  922. X    {
  923. X      c[ 9+2*j]=HEXCHAR(real_z80_mem[i+j]>>4);
  924. X      c[10+2*j]=HEXCHAR(real_z80_mem[i+j]&15);
  925. X    }
  926. X    c[73]=0;
  927. X    tmp=256-csum(c+1);
  928. X    c[73]=HEXCHAR(tmp>>4);
  929. X    c[74]=HEXCHAR(tmp&15);
  930. X    c[75]=0;
  931. X    fprintf(file,"%s\n",c);
  932. X  }
  933. X  if (i<end)
  934. X  {
  935. X    c[0]=':';
  936. X    c[1]=HEXCHAR((end-i)>>4);
  937. X    c[2]=HEXCHAR((end-i)&15);
  938. X    c[3]=HEXCHAR(i>>12);
  939. X    c[4]=HEXCHAR((i>>8)&15);
  940. X    c[5]=HEXCHAR((i>>4)&15);
  941. X    c[6]=HEXCHAR(i&15);
  942. X    c[7]='0';
  943. X    c[8]='0';
  944. X    for (j=0;j<end-i;j++)
  945. X    {
  946. X      c[ 9+2*j]=HEXCHAR(real_z80_mem[i+j]>>4);
  947. X      c[10+2*j]=HEXCHAR(real_z80_mem[i+j]&15);
  948. X    }
  949. X    c[ 9+2*(end-i)]=0;
  950. X    tmp=256-csum(c+1);
  951. X    c[ 9+2*(end-i)]=HEXCHAR(tmp>>4);
  952. X    c[10+2*(end-i)]=HEXCHAR(tmp&15);
  953. X    c[11+2*(end-i)]=0;
  954. X    fprintf(file,"%s\n",c);
  955. X  }
  956. X  fprintf(file,":0000000000\n");
  957. X  fclose(file);
  958. X}
  959. X
  960. Xmovemem(ibuf) char* ibuf;
  961. X{
  962. X  WORD start,end,new,i;
  963. X
  964. X  if(3!=sscanf(ibuf,"%*s %hx %hx %hx",&start,&end,&new)) {
  965. X    printf("usage: move old_start old_end new_start\n");
  966. X    return;
  967. X  }
  968. X
  969. X  for(i=start;i<=end;i++)
  970. X    real_z80_mem[new+(i-start)]=real_z80_mem[i];
  971. X}
  972. X
  973. Xuser_cmd(ibuf) char* ibuf; /* for us, a relocator */
  974. X{
  975. X  WORD start,end,bitmap,offset,i;
  976. X
  977. X  if(4!=sscanf(ibuf,"%*s %hx %hx %hx %hx",&start,&end,&bitmap,&offset)) {
  978. X    printf("usage: user_cmd start end bitmap offset\n");
  979. X    return;
  980. X  }
  981. X  offset&=0xff;
  982. X
  983. X  for (i=start;i<=end;i++)
  984. X    if ( real_z80_mem[bitmap+((i-start)/8)] & (1<<((i-start)%8)) )
  985. X      real_z80_mem[i]+=offset;
  986. X}
  987. SHAR_EOF
  988. $TOUCH -am 0928182090 debug.c &&
  989. chmod 0644 debug.c ||
  990. echo "restore of debug.c failed"
  991. set `wc -c debug.c`;Wc_c=$1
  992. if test "$Wc_c" != "8597"; then
  993.     echo original size 8597, current size $Wc_c
  994. fi
  995. # ============= io_ask.c ==============
  996. echo "x - extracting io_ask.c (Text)"
  997. sed 's/^X//' << 'SHAR_EOF' > io_ask.c &&
  998. X/*
  999. X
  1000. Xio_ask.c - interactive I/O for Z-80 emulator.
  1001. X
  1002. X*/
  1003. X
  1004. X#include "z80.h"
  1005. X#include <stdio.h>
  1006. X
  1007. XBYTE rdport(addr)
  1008. XBYTE addr;
  1009. X{
  1010. X  short data;
  1011. X
  1012. X  printf("Z-80 reading from port %02XH:",addr);
  1013. X  scanf("%hx",&data);
  1014. X  return (BYTE) data;
  1015. X}
  1016. X
  1017. Xwrport(addr,data)
  1018. XBYTE addr,data;
  1019. X{
  1020. X  printf("Z-80 writes %02XH to port %02XH\n",data,addr);
  1021. X}
  1022. X
  1023. XBYTE int_read()
  1024. X{
  1025. X  short data;
  1026. X
  1027. X  printf("Z-80 reading for interrupt acknowledge:");
  1028. X  scanf("%hx",&data);
  1029. X  return (BYTE) data;
  1030. X}
  1031. X
  1032. SHAR_EOF
  1033. $TOUCH -am 0928182090 io_ask.c &&
  1034. chmod 0644 io_ask.c ||
  1035. echo "restore of io_ask.c failed"
  1036. set `wc -c io_ask.c`;Wc_c=$1
  1037. if test "$Wc_c" != "462"; then
  1038.     echo original size 462, current size $Wc_c
  1039. fi
  1040. # ============= io_mem.c ==============
  1041. echo "x - extracting io_mem.c (Text)"
  1042. sed 's/^X//' << 'SHAR_EOF' > io_mem.c &&
  1043. X/*
  1044. X
  1045. Xio_mem.c: Implement a 256 byte RAM on the Z-80 I/O space.
  1046. X
  1047. X*/
  1048. X
  1049. X#include "z80.h"
  1050. X
  1051. XBYTE z80_io[256];
  1052. X
  1053. XBYTE rdport(addr)
  1054. XBYTE addr;
  1055. X{
  1056. X  return z80_io[addr];
  1057. X}
  1058. X
  1059. Xwrport(addr,data)
  1060. XBYTE addr,data;
  1061. X{
  1062. X  z80_io[addr]=data;
  1063. X}
  1064. X
  1065. XBYTE int_read()
  1066. X{
  1067. X  return 255;
  1068. X}
  1069. SHAR_EOF
  1070. $TOUCH -am 0928182090 io_mem.c &&
  1071. chmod 0644 io_mem.c ||
  1072. echo "restore of io_mem.c failed"
  1073. set `wc -c io_mem.c`;Wc_c=$1
  1074. if test "$Wc_c" != "255"; then
  1075.     echo original size 255, current size $Wc_c
  1076. fi
  1077. # ============= lh.c ==============
  1078. echo "x - extracting lh.c (Text)"
  1079. sed 's/^X//' << 'SHAR_EOF' > lh.c &&
  1080. X/*
  1081. X
  1082. XLoad .HEX format file into Z-80 memory.
  1083. X
  1084. X*/
  1085. X
  1086. X/* #include <stdio.h> */
  1087. X#define NULL 0
  1088. X#include <strings.h> 
  1089. X#include <ctype.h> 
  1090. X#include "z80.h"
  1091. X
  1092. XBYTE hexval(),hex_byte(),csum();
  1093. X
  1094. XBYTE hexval(c)
  1095. Xchar c;
  1096. X{
  1097. X  char *l;
  1098. X  static char digits[]="0123456789ABCDEF";
  1099. X
  1100. X  if (islower(c))
  1101. X    c=toupper(c);
  1102. X  l=index(digits,c);
  1103. X  if (l==NULL)
  1104. X    return 255;
  1105. X  return l-digits;
  1106. X}
  1107. X
  1108. SHAR_EOF
  1109. $TOUCH -am 0928182090 lh.c &&
  1110. chmod 0644 lh.c ||
  1111. echo "restore of lh.c failed"
  1112. set `wc -c lh.c`;Wc_c=$1
  1113. if test "$Wc_c" != "373"; then
  1114.     echo original size 373, current size $Wc_c
  1115. fi
  1116. # ============= loadhex.c ==============
  1117. echo "x - extracting loadhex.c (Text)"
  1118. sed 's/^X//' << 'SHAR_EOF' > loadhex.c &&
  1119. X/*
  1120. X
  1121. XLoad .HEX format file into Z-80 memory.
  1122. X
  1123. X*/
  1124. X
  1125. X#include <stdio.h>
  1126. X#include <strings.h>
  1127. X#include <ctype.h>
  1128. X#include "z80.h"
  1129. X
  1130. XBYTE hexval(),hex_byte(),csum();
  1131. X
  1132. Xint getline(f,l)
  1133. XFILE *f;
  1134. Xchar *l;
  1135. X{
  1136. X  int c;
  1137. X
  1138. X  while((c=getc(f))!=EOF && c!='\n')
  1139. X    *l++=c;
  1140. X  if (c==EOF)
  1141. X    return 1;
  1142. X  *l=0;
  1143. X  return 0;
  1144. X}
  1145. X
  1146. Xloadhex(f)
  1147. XFILE *f;
  1148. X{
  1149. X  char line[80],*ptr;
  1150. X  BYTE count,parse,i,cs;
  1151. X  WORD addr;
  1152. X
  1153. X  while(!getline(f,line))
  1154. X  {
  1155. X    ptr=line;
  1156. X    if (index(ptr,':')==NULL)
  1157. X      continue;
  1158. X    ptr=index(ptr,':')+1;
  1159. X    if (cs=csum(ptr))
  1160. X    {
  1161. X      printf("Checksum error: %s\n",ptr);
  1162. X      continue;
  1163. X    }
  1164. X    count=hex_byte(ptr);
  1165. X    ptr+= 2;
  1166. X    addr=(hex_byte(ptr)<<8)|hex_byte(ptr+2);
  1167. X    ptr+= 4;
  1168. X    parse=hex_byte(ptr);
  1169. X    ptr+= 2;
  1170. X
  1171. X    /* check parse byte if you want... */
  1172. X
  1173. X    for(i=0;i<count;i++,ptr+= 2)
  1174. X    {
  1175. X      real_z80_mem[addr+i]=hex_byte(ptr);
  1176. X    }
  1177. X  }
  1178. X  
  1179. X}
  1180. X
  1181. XBYTE hex_byte(c)
  1182. Xchar *c;
  1183. X{
  1184. X  return ((hexval(*c)<<4)|hexval(*(c+1)));
  1185. X}
  1186. X
  1187. XBYTE hexval(c)
  1188. Xchar c;
  1189. X{
  1190. X  char *l;
  1191. X  static char digits[]="0123456789ABCDEF";
  1192. X
  1193. X  if (islower(c))
  1194. X    c=toupper(c);
  1195. X  l=index(digits,c);
  1196. X  if (l==NULL)
  1197. X    return 255;
  1198. X  return l-digits;
  1199. X}
  1200. X
  1201. XBYTE csum(l)
  1202. Xchar *l;
  1203. X{
  1204. X  BYTE csum=0;
  1205. X
  1206. X  while(strlen(l))
  1207. X  {
  1208. X    csum+=(hex_byte(l)&0xff);
  1209. X    l+=2;
  1210. X  }
  1211. X
  1212. X  return csum;
  1213. X}
  1214. SHAR_EOF
  1215. $TOUCH -am 0928182090 loadhex.c &&
  1216. chmod 0644 loadhex.c ||
  1217. echo "restore of loadhex.c failed"
  1218. set `wc -c loadhex.c`;Wc_c=$1
  1219. if test "$Wc_c" != "1262"; then
  1220.     echo original size 1262, current size $Wc_c
  1221. fi
  1222. # ============= makedrive.c ==============
  1223. echo "x - extracting makedrive.c (Text)"
  1224. sed 's/^X//' << 'SHAR_EOF' > makedrive.c &&
  1225. X/*
  1226. X
  1227. Xmakedrive.c - creates a "drive device" file for CP/M - really a file
  1228. Xwith a size a multiple of 2K and more than 128K, with the first 16K
  1229. Xfilled with $E5, and a hole for the rest up to the EOF. This creates
  1230. Xa file that takes up 16K on disk, but has a huge EOF. Under CP/M, the
  1231. XEOF of a "drive device" file defines its size, which (of course)
  1232. Xdoesn't change.
  1233. X
  1234. X*/
  1235. X
  1236. X#include <stdio.h>
  1237. X
  1238. Xextern int errno;
  1239. Xextern char *sys_errlist[];
  1240. X
  1241. Xusage(name)
  1242. Xchar *name;
  1243. X{
  1244. X  printf("Usage: %s [size] [filename]\n\n",name);
  1245. X  printf("size is in K-bytes and must be an even number 128 or greater.\n\n");
  1246. X  exit(1);
  1247. X}
  1248. X
  1249. Xmain(argc,argv)
  1250. Xint argc;
  1251. Xchar **argv;
  1252. X{
  1253. X  int size,i;
  1254. X  FILE *f;
  1255. X
  1256. X  if (argc!=3)
  1257. X    usage(*argv);
  1258. X
  1259. X  size=atoi(argv[1]);
  1260. X
  1261. X  if (size<128 || size%2)
  1262. X    usage(*argv);
  1263. X
  1264. X  f=fopen(argv[2],"w");
  1265. X  if (f==NULL)
  1266. X  {
  1267. X    printf("%s: %s - %s\n",*argv,argv[2],sys_errlist[errno]);
  1268. X    exit(1);
  1269. X  }
  1270. X
  1271. X  for (i=0;i<16384*4;i++) /* write out a blank directory */
  1272. X    putc(0xE5,f);
  1273. X
  1274. X  fseek(f,(long)(1024*size-1),0); /* make a big hole */
  1275. X  putc(0xE5,f);
  1276. X
  1277. X  fclose(f);
  1278. X
  1279. X}
  1280. SHAR_EOF
  1281. $TOUCH -am 0928182090 makedrive.c &&
  1282. chmod 0644 makedrive.c ||
  1283. echo "restore of makedrive.c failed"
  1284. set `wc -c makedrive.c`;Wc_c=$1
  1285. if test "$Wc_c" != "1062"; then
  1286.     echo original size 1062, current size $Wc_c
  1287. fi
  1288. # ============= udbg.c ==============
  1289. echo "x - extracting udbg.c (Text)"
  1290. sed 's/^X//' << 'SHAR_EOF' > udbg.c &&
  1291. X/*
  1292. X
  1293. Xdebug.c - debugger for z-80 emulator.
  1294. X
  1295. X*/
  1296. X
  1297. X#include <stdio.h>
  1298. X#include <setjmp.h>
  1299. X#include <signal.h>
  1300. X
  1301. X#include "z80.h"
  1302. Xextern char *sys_errlist[];
  1303. Xextern int errno;
  1304. X
  1305. Xjmp_buf lj;
  1306. X
  1307. Xvoid int_handler()
  1308. X{
  1309. X  longjmp(lj);
  1310. X}
  1311. X
  1312. Xlong z80_memlines[65536];
  1313. Xlong z80_memseeks[65536];
  1314. XFILE *z80_file;
  1315. X
  1316. X
  1317. X#include <sgtty.h>
  1318. Xextern struct sgttyb tty_sgtty_data;
  1319. X
  1320. X
  1321. Xdebug_write(x,y)
  1322. X     WORD x;
  1323. X     BYTE y;
  1324. X{
  1325. X  if(x==TWRTval) {        /* bdos storage of user # == 0xedfe*/
  1326. X    printf("\n\r0x%04x:%02x\n\r",x,y);
  1327. X    debugit();
  1328. X  }
  1329. X  real_z80_mem[x]=y;
  1330. X}
  1331. X
  1332. X
  1333. Xdebugit()
  1334. X{
  1335. X  int i;
  1336. X
  1337. X  gtty(fileno(stdin),&tty_sgtty_data);
  1338. X  tty_sgtty_data.sg_flags&=~RAW;
  1339. X  tty_sgtty_data.sg_flags|=ECHO;
  1340. X  stty(fileno(stdin),&tty_sgtty_data);
  1341. X
  1342. X  z80_file = 0;
  1343. X  while(1)
  1344. X  {
  1345. X    char ibuf[128], *istat;
  1346. X    
  1347. X    char cmd_char;
  1348. X
  1349. X    do {
  1350. X      printf("\n>");
  1351. X      bzero(ibuf,127);
  1352. X      istat = fgets(ibuf, 127, stdin);
  1353. X    } while (istat && strlen(ibuf)<2);
  1354. X    if(!istat) break;
  1355. X    
  1356. X    cmd_char = ibuf[0];
  1357. X    switch(cmd_char)
  1358. X    {
  1359. X    case 'd':dump(ibuf);
  1360. X    break;
  1361. X    case 'G':/* z80_run(ibuf) */
  1362. X  gtty(fileno(stdin),&tty_sgtty_data);
  1363. X  tty_sgtty_data.sg_flags|=RAW;
  1364. X  tty_sgtty_data.sg_flags&=~ECHO;
  1365. X  stty(fileno(stdin),&tty_sgtty_data);
  1366. X      return 1;
  1367. X    case 'g':/* z80_run(ibuf) */
  1368. X  gtty(fileno(stdin),&tty_sgtty_data);
  1369. X  tty_sgtty_data.sg_flags|=RAW;
  1370. X  tty_sgtty_data.sg_flags&=~ECHO;
  1371. X  stty(fileno(stdin),&tty_sgtty_data);
  1372. X      return 0;
  1373. X    break;
  1374. X    case 's':z80_instr(ibuf);
  1375. X      /* break; */ /* really fall through */
  1376. X    case 'c':pr_reg(ibuf);
  1377. X    break;
  1378. X    case 'l':gethex(ibuf);
  1379. X    break;
  1380. X    case 'b':getbin(ibuf);
  1381. X    break;
  1382. X    case 'm':movemem(ibuf);
  1383. X    break;
  1384. X    case 'w':writehex(ibuf);
  1385. X    break;
  1386. X    case 'y':getlines(ibuf);
  1387. X    break;
  1388. X    case 'r':set_reg(ibuf);
  1389. X    break;
  1390. X    case 'q':
  1391. X  gtty(fileno(stdin),&tty_sgtty_data);
  1392. X  tty_sgtty_data.sg_flags|=RAW;
  1393. X  tty_sgtty_data.sg_flags&=~ECHO;
  1394. X  stty(fileno(stdin),&tty_sgtty_data);
  1395. X      exit(0);
  1396. X    break;
  1397. X    case 'e':edit(ibuf);
  1398. X    break;
  1399. X    case '$':user_cmd(ibuf);
  1400. X    break;
  1401. X    default:help(ibuf);
  1402. X    break;
  1403. X    }
  1404. X  }
  1405. X
  1406. X}
  1407. X
  1408. X/*
  1409. X
  1410. Xon-line help
  1411. X
  1412. X*/
  1413. X
  1414. Xhelp(ibuf) char* ibuf;
  1415. X{
  1416. X  printf("\nb file           - load a binary image\n");
  1417. X  printf("c                - display register values\n");
  1418. X  printf("d start [len]    - display memory\n");
  1419. X  printf("e start          - edit memory\n");
  1420. X  printf("g                - start Z-80 running\n");
  1421. X  printf("l file           - load hex file\n");
  1422. X  printf("m start end dest - move a chunk of memory\n");
  1423. X  printf("q                - quit\n");
  1424. X  printf("r reg val        - change register/flag value\n");
  1425. X  printf("s                - single step\n");
  1426. X  printf("w start end file - write hex file\n");
  1427. X  printf("y file           - read lines file\n");
  1428. X  printf("$                - execute user command\n");
  1429. X}
  1430. X
  1431. X/*
  1432. X
  1433. Xdump
  1434. X
  1435. X*/
  1436. X
  1437. Xdump(ibuf) char* ibuf;
  1438. X{
  1439. X  int start,end=0;
  1440. X
  1441. X  if(2!=sscanf(ibuf,"%*s %x %x",&start,&end)) {
  1442. X    printf("usage: dump start end\n");
  1443. X    return;
  1444. X  }
  1445. X  pr_mem(start,end);
  1446. X}
  1447. X
  1448. X/*
  1449. X
  1450. Xedit
  1451. X
  1452. X*/
  1453. X
  1454. Xedit(ibuf) char* ibuf;
  1455. X{
  1456. X  int start,byte;
  1457. X  if(2!=sscanf(ibuf,"%*s %x %x",&start,&byte)) {
  1458. X    printf("usage: edit address value\n");
  1459. X    return;
  1460. X  }
  1461. X  start&=0xffff;
  1462. X  byte&=0xff;
  1463. X  real_z80_mem[start]=byte;
  1464. X}
  1465. X
  1466. X/*
  1467. X
  1468. Xset registers
  1469. X
  1470. X*/
  1471. X
  1472. Xset_reg(ibuf) char* ibuf;
  1473. X{
  1474. X  char reg[80];
  1475. X  int i;
  1476. X  if(2!=sscanf(ibuf,"%*s %s %x",reg, &i)) {
  1477. X    printf("usage: set register value\n");
  1478. X    return;
  1479. X  }
  1480. X  i&=0xffff;
  1481. X  if (!strcmp(reg,"pc"))
  1482. X    PC=i;
  1483. X  else if (!strcmp(reg,"sp"))
  1484. X    SP=i;
  1485. X  else if (!strcmp(reg,"af"))
  1486. X    AF=i;
  1487. X  else if (!strcmp(reg,"bc"))
  1488. X    BC=i;
  1489. X  else if (!strcmp(reg,"de"))
  1490. X    DE=i;
  1491. X  else if (!strcmp(reg,"hl"))
  1492. X    HL=i;
  1493. X  else if (!strcmp(reg,"af'"))
  1494. X    AF2=i;
  1495. X  else if (!strcmp(reg,"bc'"))
  1496. X    BC2=i;
  1497. X  else if (!strcmp(reg,"de'"))
  1498. X    DE2=i;
  1499. X  else if (!strcmp(reg,"hl'"))
  1500. X    HL2=i;
  1501. X  else if (!strcmp(reg,"ix"))
  1502. X    IX=i;
  1503. X  else if (!strcmp(reg,"iy"))
  1504. X    IY=i;
  1505. X  else if (!strcmp(reg,"i"))
  1506. X    IR=(IR&0xff)|(i<<8);
  1507. X  else if (!strcmp(reg,"r"))
  1508. X    IR=(IR&0xff00)|i;
  1509. X  else {
  1510. X    printf("register should be one of: pc sp af bc de hl af' bc' de' hl' ix iy i r\n");
  1511. X  }
  1512. X}
  1513. X
  1514. X/*
  1515. X
  1516. Xdump out memory for the user. A is the starting address. L is the amount
  1517. Xof dumping he wants. if L is 0, a default value is supplied.
  1518. X
  1519. X*/
  1520. X
  1521. Xpr_mem(a,l)
  1522. XWORD a,l;
  1523. X{
  1524. X  WORD i;
  1525. X  int counter=0;
  1526. X
  1527. X  if (!l)
  1528. X    l=0x100;
  1529. X  for(i=0;i<l;i++)
  1530. X  {
  1531. X    if (!(counter%16))
  1532. X      printf("%04X- ",(a+i)&0xffff);
  1533. X
  1534. X    printf("%02X ",real_z80_mem[(a+i)&0xffff]);
  1535. X    counter++;
  1536. X
  1537. X    if (!(counter%16))
  1538. X    {
  1539. X      char c; int j;
  1540. X      for (j=15;j>=0;j--)
  1541. X      {
  1542. X    c=real_z80_mem[(a+i-j)&0xffff]&0x7f;
  1543. X        putchar( ((c>0x20) && (c<0x7f))?c:'.' );
  1544. X      }
  1545. X      printf("\n");
  1546. X    }
  1547. X  }
  1548. X  if (counter%16)
  1549. X  {
  1550. X    int j;
  1551. X    char c;
  1552. X    for(j=counter%16;j>0;j--)
  1553. X    {
  1554. X      c=real_z80_mem[(a+i-j)&0xffff]&0x7f;
  1555. X      putchar( ((c>0x20) && (c<0x7f))?c:'.' );
  1556. X    }
  1557. X    printf("\n");
  1558. X  }
  1559. X}
  1560. X
  1561. Xshow_debug_line(addr) WORD addr;
  1562. X{
  1563. X  char ibuf[1024];
  1564. X  int ilow = addr, ihi = addr;
  1565. X  if(z80_file) {
  1566. X    while(ilow>0 && !z80_memlines[ilow]) ilow--;
  1567. X    while(ihi<65536 && !z80_memlines[ilow]) ihi++;
  1568. X    printf("(range %d %d)\n",ilow,ihi);
  1569. X    fseek(z80_file,z80_memseeks[ilow],0);
  1570. X    fgets(ibuf,1023,z80_file);
  1571. X    printf("%d: %s",z80_memlines[ilow],ibuf); /* \n included in ibuf... */
  1572. X  }
  1573. X}
  1574. X
  1575. Xpr_reg(ibuf) char* ibuf;
  1576. X{
  1577. X  static char *flag_chars="CNVxHxZS";
  1578. X  int i;
  1579. X
  1580. X  printf("\nA =%02XH BC =%04XH DE =%04XH HL =%04XH SP=%04XH IX=%04XH\n"
  1581. X      ,AF>>8,BC,DE,HL,SP,IX);
  1582. X  printf("A'=%02XH BC'=%04XH DE'=%04XH HL'=%04XH PC=%04XH IY=%04XH\n"
  1583. X      ,AF2>>8,BC2,DE2,HL2,PC,IY);
  1584. X
  1585. X  printf("\nI=%02XH R=%02XH  F=",IR>>8,IR%0xff);
  1586. X  for(i=7;i>=0;i--)
  1587. X    putchar( (AF&(1<<i))?flag_chars[i]:'-' );
  1588. X  printf(" F'=");
  1589. X  for(i=7;i>=0;i--)
  1590. X    putchar( (AF2&(1<<i))?flag_chars[i]:'-' );
  1591. X  printf("  IFF1=%c  IFF2=%c"
  1592. X      ,(INT_FLAGS&IFF1)?'1':'-',(INT_FLAGS&IFF2)?'1':'-');
  1593. X
  1594. X  printf("\n(PC)=");
  1595. X  for(i=PC; i<PC+16; i++) {
  1596. X    printf("%02X ",real_z80_mem[i]);
  1597. X  }
  1598. X  printf("\n(HL)=");
  1599. X  for(i=HL; i<HL+16; i++) {
  1600. X    printf("%02X ",real_z80_mem[i]);
  1601. X  }
  1602. X  printf("\n(SP)=");
  1603. X  for(i=SP; i<SP+16; i++) {
  1604. X    printf("%02X ",real_z80_mem[i]);
  1605. X  }
  1606. X  printf("\n");
  1607. X
  1608. X  show_debug_line(PC);
  1609. X}
  1610. X
  1611. Xgetlines(ibuf) char* ibuf;
  1612. X{
  1613. X  char fname[80];
  1614. X  char lbuf[1024], *lstat;
  1615. X
  1616. X  if(z80_file) {
  1617. X    int i;
  1618. X    fclose(z80_file);
  1619. X    for(i = 0; i<65536; i++) {
  1620. X      z80_memlines[i] = 0;
  1621. X      z80_memseeks[i] = 0;
  1622. X    }
  1623. X  }
  1624. X  sscanf(ibuf,"%*s %s",fname);
  1625. X
  1626. X  z80_file=fopen(fname,"r");
  1627. X  if (z80_file==NULL)
  1628. X  {
  1629. X    printf("%s: %s",fname,sys_errlist[errno]);
  1630. X    return;
  1631. X  }
  1632. X  /* long z80_memlines[65536]; */
  1633. X  do {
  1634. X    int addr, line, told;
  1635. X    told = ftell(z80_file);
  1636. X    lstat = fgets(lbuf, 1023, z80_file);
  1637. X    if(!lstat) break;
  1638. X    sscanf(lbuf,"%d: %x",&line,&addr);
  1639. X    z80_memlines[addr] = line;
  1640. X    z80_memseeks[addr] = told;
  1641. X  } while(lstat);
  1642. X
  1643. X  /* fclose(file); */
  1644. X}
  1645. X
  1646. X
  1647. Xgethex(ibuf) char* ibuf;
  1648. X{
  1649. X  char fname[80];
  1650. X  FILE *file;
  1651. X
  1652. X  sscanf(ibuf,"%*s %s",fname);
  1653. X
  1654. X  file=fopen(fname,"r");
  1655. X  if (file==NULL)
  1656. X  {
  1657. X    printf("%s: %s",fname,sys_errlist[errno]);
  1658. X    return;
  1659. X  }
  1660. X  loadhex(file);
  1661. X  fclose(file);
  1662. X}
  1663. X
  1664. Xgetbin(ibuf) char* ibuf;
  1665. X{
  1666. X  char fname[80];
  1667. X  FILE *file;
  1668. X  WORD icount=0,count=0;
  1669. X
  1670. X  if(2!=sscanf(ibuf,"%*s %hx %s",&icount,fname)) {
  1671. X    printf("usage: getbin offset filename\n");
  1672. X    return;
  1673. X  };
  1674. X
  1675. X  file=fopen(fname,"r");
  1676. X  if (file==NULL)
  1677. X  {
  1678. X    printf("%s: %s",fname,sys_errlist[errno]);
  1679. X    return;
  1680. X  }
  1681. X  count=icount;
  1682. X  printf("loading %s into %04x\n",fname,count);
  1683. X  while (!feof(file))
  1684. X    real_z80_mem[count++]=getc(file);
  1685. X  fclose(file);
  1686. X  printf("loaded %d bytes (save %d foo.com)\n",count-icount,((count-icount)/256)+1);
  1687. X}
  1688. X
  1689. Xextern BYTE csum();
  1690. X/*
  1691. X#define HEXCHAR(a) ( ((a)>=10) ? ((a)+'a'-10) : ((a)+'0') )
  1692. X*/
  1693. Xchar HEXCHAR(a)
  1694. Xchar a;
  1695. X{
  1696. X  return ( ((a)>=10) ? ((a)+'a'-10) : ((a)+'0') );
  1697. X}
  1698. Xwritehex(ibuf) char* ibuf;
  1699. X{
  1700. X  char fname[80],c[80];
  1701. X  FILE *file;
  1702. X  WORD start,end,i,j;
  1703. X  BYTE tmp;
  1704. X  char counter=0;
  1705. X
  1706. X  if(3!=sscanf(ibuf,"%*s %hx %hx %s",&start,&end,fname)) {
  1707. X    printf("usage: write start end filename\n");
  1708. X    return;
  1709. X  }
  1710. X  end++;
  1711. X
  1712. X  file=fopen(fname,"a");
  1713. X  if (file==NULL)
  1714. X  {
  1715. X    printf("%s: %s",fname,sys_errlist[errno]);
  1716. X    return;
  1717. X  }
  1718. X  for(i=start;i<=end-32;i+=32)
  1719. X  {
  1720. X    strcpy(c,":20");
  1721. X    c[3]=HEXCHAR(i>>12);
  1722. X    c[4]=HEXCHAR((i>>8)&15);
  1723. X    c[5]=HEXCHAR((i>>4)&15);
  1724. X    c[6]=HEXCHAR(i&15);
  1725. X    c[7]='0';
  1726. X    c[8]='0';
  1727. X    for(j=0;j<32;j++)
  1728. X    {
  1729. X      c[ 9+2*j]=HEXCHAR(real_z80_mem[i+j]>>4);
  1730. X      c[10+2*j]=HEXCHAR(real_z80_mem[i+j]&15);
  1731. X    }
  1732. X    c[73]=0;
  1733. X    tmp=256-csum(c+1);
  1734. X    c[73]=HEXCHAR(tmp>>4);
  1735. X    c[74]=HEXCHAR(tmp&15);
  1736. X    c[75]=0;
  1737. X    fprintf(file,"%s\n",c);
  1738. X  }
  1739. X  if (i<end)
  1740. X  {
  1741. X    c[1]=HEXCHAR((end-i)>>4);
  1742. X    c[2]=HEXCHAR((end-i)&15);
  1743. X    c[3]=HEXCHAR(i>>12);
  1744. X    c[4]=HEXCHAR((i>>8)&15);
  1745. X    c[5]=HEXCHAR((i>>4)&15);
  1746. X    c[6]=HEXCHAR(i&15);
  1747. X    c[7]='0';
  1748. X    c[8]='0';
  1749. X    for (j=0;j<end-i;j++)
  1750. X    {
  1751. X      c[ 9+2*j]=HEXCHAR(real_z80_mem[i+j]>>4);
  1752. X      c[10+2*j]=HEXCHAR(real_z80_mem[i+j]&15);
  1753. X    }
  1754. X    c[ 9+2*(end-i)]=0;
  1755. X    tmp=256-csum(c+1);
  1756. X    c[ 9+2*(end-i)]=HEXCHAR(tmp>>4);
  1757. X    c[10+2*(end-i)]=HEXCHAR(tmp&15);
  1758. X    c[11+2*(end-i)]=0;
  1759. X    fprintf(file,"%s\n",c);
  1760. X  }
  1761. X  fprintf(file,":0000000000\n");
  1762. X  fclose(file);
  1763. X}
  1764. X
  1765. Xmovemem(ibuf) char* ibuf;
  1766. X{
  1767. X  WORD start,end,new,i;
  1768. X
  1769. X  if(3!=sscanf(ibuf,"%*s %hx %hx %hx",&start,&end,&new)) {
  1770. X    printf("usage: move old_start old_end new_start\n");
  1771. X    return;
  1772. X  }
  1773. X
  1774. X  for(i=start;i<=end;i++)
  1775. X    real_z80_mem[new+(i-start)]=real_z80_mem[i];
  1776. X}
  1777. X
  1778. Xuser_cmd(ibuf) char* ibuf; /* for us, a relocator */
  1779. X{
  1780. X  WORD start,end,bitmap,offset,i;
  1781. X
  1782. X  if(4!=sscanf(ibuf,"%*s %hx %hx %hx %hx",&start,&end,&bitmap,&offset)) {
  1783. X    printf("usage: user_cmd start end bitmap offset\n");
  1784. X    return;
  1785. X  }
  1786. X  offset&=0xff;
  1787. X
  1788. X  for (i=start;i<=end;i++)
  1789. X    if ( real_z80_mem[bitmap+((i-start)/8)] & (1<<((i-start)%8)) )
  1790. X      real_z80_mem[i]+=offset;
  1791. X}
  1792. SHAR_EOF
  1793. $TOUCH -am 0928182090 udbg.c &&
  1794. chmod 0644 udbg.c ||
  1795. echo "restore of udbg.c failed"
  1796. set `wc -c udbg.c`;Wc_c=$1
  1797. if test "$Wc_c" != "9809"; then
  1798.     echo original size 9809, current size $Wc_c
  1799. fi
  1800. # ============= upm.c ==============
  1801. echo "x - extracting upm.c (Text)"
  1802. sed 's/^X//' << 'SHAR_EOF' > upm.c &&
  1803. X/*
  1804. X
  1805. Xup/m - unix CP/M.
  1806. X
  1807. X(C) MCMXC - Nick Sayer - All rights reserved.
  1808. X
  1809. XSee COPYRIGHT file for more details.
  1810. X
  1811. X
  1812. XConfiguration section.
  1813. X
  1814. X
  1815. XCPM_FILE - default file with CP/M HEX images.
  1816. X
  1817. XAddresses 0-2K are CCP, 2K-5.5K - BDOS. 5.5K-16K - BIOS. Address 65535
  1818. Xwill have the length (in pages) of CP/M.
  1819. X
  1820. XAddresses 16K-? - relocation bitmap. Each bit in the bitmap represents
  1821. Xa BYTE in 0-16K. If the bit is 1, the high byte of the first address of
  1822. Xthe destination address for the CCP should be added to the byte in 0-16K
  1823. Ximage. That image is then moved to the proper location. The PC is set to
  1824. X32K and the Z-80 starts running. The high byte of the first byte of the
  1825. XCCP destination address is gotten from address 65535. This value is
  1826. Xthen adjusted if CP/M is to be relocated lower than the default
  1827. Xtop of memory. The CP/M image to load should have a resident run address
  1828. Xbefore relocation of 0.
  1829. X
  1830. X*/
  1831. X#define CPM_FILE "CPM"
  1832. X
  1833. X#include <strings.h>
  1834. X#include <ctype.h>
  1835. X#include <sgtty.h>
  1836. X#include <signal.h>
  1837. X
  1838. X#include "upm.h"
  1839. X
  1840. XWORD topmem=256;       /* These may be changed by arguments */
  1841. Xchar *cpm_file=CPM_FILE;
  1842. X
  1843. Xstruct sgttyb tty_sgtty_data;
  1844. X
  1845. Xstatic BYTE dph[32]={
  1846. X
  1847. X/* Disk Paramater Header (diskbufs[]) */
  1848. X
  1849. X0x00,0x00,    /* TRANSTABLE unused */
  1850. X0x00,0x00,    /* unused */
  1851. X0x00,0x00,
  1852. X0x00,0x00,
  1853. X0x80,0xff,    /* DIRBUF - patch with topmem-1 later */
  1854. X0x10,0xff,    /* DPB - patch with OUR page no. */
  1855. X0x00,0x00,    /* CHKVEC - not used */
  1856. X0x20,0xff,    /* ALLOCVEC - patch with OUR page no. */
  1857. X
  1858. X/* Disk Paramater Block */
  1859. X
  1860. X0x40,0x00,    /* Sectors per track */
  1861. X0x04,        /* Block Shift */
  1862. X0x0f,        /* Block Mask */
  1863. X0x00,        /* Extent Mask */
  1864. X0x00,0x10,    /* Blocks on device - patch if variable size implemented */
  1865. X0xff,0x01,    /* Directory entries -1 */
  1866. X0xff,0x00,    /* Allocation masks for directory */
  1867. X0x00,0x00,    /* Check vector size - patch if checkvecs implemented */
  1868. X0x00,0x00,    /* offset to first user-track */
  1869. X0x00        /* spare */
  1870. X};
  1871. X
  1872. X/* These are externs in upm.h, but they have to be declared somewhere. */
  1873. X
  1874. XFILE *disks[16],*devices[5];
  1875. XWORD diskbufs[16];
  1876. XBYTE ccp_image[SIZE_CCP_IMAGE];
  1877. XWORD ccp_start;
  1878. X
  1879. X/*
  1880. X
  1881. Xrelocade(address);
  1882. XBYTE address;
  1883. X
  1884. XRelocate CP/M image at 0000-4000 using bitmap at 4000-4800.
  1885. XCopy image to new location, and copy first 5.5K to ccp_image[];
  1886. XStop if we get to the top of RAM.
  1887. X
  1888. X*/
  1889. X
  1890. Xrelocate(add,len)
  1891. XBYTE add;
  1892. X{
  1893. X  WORD i;
  1894. X
  1895. X  for (i=0;i!=(256*len);i++)
  1896. X  {
  1897. X    if ( real_z80_mem[16384+(i>>3)]&(1<<(i&7)) )
  1898. X      real_z80_mem[i]=real_z80_mem[i]+add;
  1899. X    real_z80_mem[i+(add<<8)]=real_z80_mem[i];
  1900. X    if (i<SIZE_CCP_IMAGE)
  1901. X      ccp_image[i]=real_z80_mem[i];
  1902. X  }
  1903. X}
  1904. Xint debugflag = 0;
  1905. Xint dlogflag = 0;
  1906. X
  1907. Xdebugit();
  1908. X
  1909. Xmain(argc,argv)
  1910. Xint argc;
  1911. Xchar **argv;
  1912. X{
  1913. X  FILE *cpm;
  1914. X  char line[80];
  1915. X  int i;
  1916. X
  1917. X  signal(SIGINT,debugit);
  1918. X
  1919. X  for(i=0;i<16;i++)
  1920. X  {
  1921. X    disks[i]=NULL;
  1922. X    devices[i%5]=NULL; /* hack: only do 0-4 */
  1923. X  }
  1924. X
  1925. X/* OPEN ~/.upmrc, send each line to process_args(line); */
  1926. X
  1927. X  argc--; argv++;
  1928. X  for(;argc--;argv++)
  1929. X    process_args(*argv);
  1930. X
  1931. X  if (disks[0]==NULL)
  1932. X  {
  1933. X    printf("A: must be assigned.\n");
  1934. X    exit(0);
  1935. X  }
  1936. X
  1937. X/*
  1938. X
  1939. XFor each non-null pointer in disks[], lower topmem, and save the pointer
  1940. Xto diskbufs[]. This assigns space for the allocation vector, and the
  1941. XDPH/DPB. Then copy in a "standard" DPH/DPB into the bottom. We'll
  1942. Xpatch it later.
  1943. X
  1944. XWe really should allow disks to be sized at runtime, but for now
  1945. Xthey're fixed at 8MB, so we lower topmem 3 for each one. 2 pages
  1946. Xfor the alloc table, another page (actually 32 bytes)
  1947. Xfor the miscelany.
  1948. X
  1949. X*/
  1950. X
  1951. X  for(i=0;i!=16;i++)
  1952. X  {
  1953. X    char j;
  1954. X
  1955. X    if (disks[i]==NULL)
  1956. X      continue;
  1957. X    topmem-=3;
  1958. X    diskbufs[i]=topmem<<8;
  1959. X    for(j=0;j!=32;j++)
  1960. X      real_z80_mem[diskbufs[i]+j]=dph[j];
  1961. X    real_z80_mem[diskbufs[i]+0x0b]=real_z80_mem[diskbufs[i]+0x0f]=topmem;
  1962. X  }
  1963. X
  1964. X/*
  1965. X
  1966. XNow for each non-null disk[] readjust the dirbuf pointer.
  1967. XWe couldn't do it before because we didn't have a final
  1968. Xlocation for dirbuf. topmem-1 is the high-byte of the
  1969. Xfinal location for dirbuf. the low byte is 0x80.
  1970. XThis page of memory is shared with the BIOS "jump" table.
  1971. X
  1972. X*/
  1973. X
  1974. X  for(i=0;i!=16;i++)
  1975. X  {
  1976. X    if (disks[i]==NULL)
  1977. X      continue;
  1978. X    real_z80_mem[diskbufs[i]+9]=topmem-1;
  1979. X  }
  1980. X
  1981. X  cpm=fopen(cpm_file,"r");
  1982. X  if (cpm==NULL)
  1983. X  {
  1984. X    printf("Can't open CP/M binaries: %s\n",sys_errlist[errno]);
  1985. X    exit(1);
  1986. X  }
  1987. X  loadhex(cpm);
  1988. X
  1989. X  ccp_start=(topmem-real_z80_mem[65535])<<8;
  1990. X  relocate(topmem-real_z80_mem[65535],real_z80_mem[65535]);
  1991. X
  1992. X  PC=0x8000;
  1993. X
  1994. X/*
  1995. X
  1996. XNow set up the terminal. Just toggling RAW should be enough.
  1997. X
  1998. X*/
  1999. X
  2000. X  gtty(fileno(stdin),&tty_sgtty_data);
  2001. X  tty_sgtty_data.sg_flags|=RAW;
  2002. X  tty_sgtty_data.sg_flags&=~ECHO;
  2003. X  stty(fileno(stdin),&tty_sgtty_data);
  2004. X
  2005. X  do
  2006. X  { z80_run();
  2007. X    if(debugflag>1 && debugit()) PC++;
  2008. X    else if(bios()) break;
  2009. X  } while(1); /*  }  while(!bios()); */
  2010. X
  2011. X  gtty(fileno(stdin),&tty_sgtty_data);
  2012. X  tty_sgtty_data.sg_flags&=~RAW;
  2013. X  tty_sgtty_data.sg_flags|=ECHO;
  2014. X  stty(fileno(stdin),&tty_sgtty_data);
  2015. X}
  2016. X
  2017. X/*
  2018. X
  2019. XThe arguments can include A:file-O:file, {TY, LP, PT, U1, U2}:file,
  2020. Xmem:0-128.
  2021. X
  2022. XDisk files are fopen()ed "r+", and are assigned to disks[].
  2023. XDevice files are fopen()ed "r+" and are assigned to devices[], except
  2024. Xfor LP:, which is fopen()ed "w".
  2025. X
  2026. XThe value after mem: lowers the top of memory by that many pages (256
  2027. Xbytes) to save space for things like BYE, etc.
  2028. X
  2029. XThe arguments MUST be stripped of white-spaces.
  2030. X
  2031. X*/
  2032. X
  2033. Xprocess_args(arg)
  2034. Xchar *arg;
  2035. X{
  2036. X  char i,left[80],*right;
  2037. X
  2038. X    if (index(arg,':')==NULL)
  2039. X    {
  2040. X      printf("Missing ':' in argument.\n");
  2041. X      return;
  2042. X    }
  2043. X
  2044. X    strcpy(left,arg);
  2045. X    right=index(left,':')+1;
  2046. X    *index(left,':')='\0';
  2047. X    for(i=0;i!=strlen(left);i++)
  2048. X      if (islower(left[i]))
  2049. X        left[i]=toupper(left[i]);
  2050. X
  2051. X    if (strlen(left)==1 && (*left<='O') && (*left>='A'))
  2052. X    {
  2053. X      disks[*left-'A']=fopen(right,"r+");
  2054. X      return;
  2055. X    }
  2056. X    if (!strcmp(left,"MEM"))
  2057. X    {
  2058. X      topmem-=atoi(right);
  2059. X      return;
  2060. X    }
  2061. X    if (!strcmp(left,"TY"))
  2062. X    {
  2063. X      devices[F_TY]=fopen(right,"r+");
  2064. X      return;
  2065. X    }
  2066. X    if (!strcmp(left,"PT"))
  2067. X    {
  2068. X      devices[F_PT]=fopen(right,"r+");
  2069. X      return;
  2070. X    }
  2071. X    if (!strcmp(left,"LP"))
  2072. X    {
  2073. X      devices[F_LP]=fopen(right,"w");
  2074. X      return;
  2075. X    }
  2076. X    if (!strcmp(left,"U1"))
  2077. X    {
  2078. X      devices[F_U1]=fopen(right,"r+");
  2079. X      return;
  2080. X    }
  2081. X    if (!strcmp(left,"U2"))
  2082. X    {
  2083. X      devices[F_U2]=fopen(right,"r+");
  2084. X      return;
  2085. X    }
  2086. X    if (!strcmp(left,"DEBUG"))
  2087. X    {
  2088. X      debugflag=atoi(right);
  2089. X      return;
  2090. X    }
  2091. X    if (!strcmp(left,"DLOG"))
  2092. X    {
  2093. X      dlogflag=atoi(right);
  2094. X      return;
  2095. X    }
  2096. X    if (!strcmp(left,"BIOS"))
  2097. X    {
  2098. X      biosflag=atoi(right);
  2099. X      return;
  2100. X    }
  2101. X    if (!strcmp(left,"TRAP"))
  2102. X    {
  2103. X      sscanf(right,"%4x",&TRAPval);
  2104. X      return;
  2105. X    }
  2106. X    if (!strcmp(left,"TWRT"))
  2107. X    {
  2108. X      sscanf(right,"%4x",&TWRTval);
  2109. X      return;
  2110. X    }
  2111. X}
  2112. X
  2113. Xcoredump()
  2114. X{
  2115. X  FILE *qb;
  2116. X  int i;
  2117. X
  2118. X  qb=fopen("mem","w");
  2119. X  for(i=0;i!=65536;i++)
  2120. X    putc(real_z80_mem[i],qb);
  2121. X  fclose(qb);
  2122. X}
  2123. SHAR_EOF
  2124. $TOUCH -am 0928214490 upm.c &&
  2125. chmod 0644 upm.c ||
  2126. echo "restore of upm.c failed"
  2127. set `wc -c upm.c`;Wc_c=$1
  2128. if test "$Wc_c" != "6850"; then
  2129.     echo original size 6850, current size $Wc_c
  2130. fi
  2131. # ============= upm.h ==============
  2132. echo "x - extracting upm.h (Text)"
  2133. sed 's/^X//' << 'SHAR_EOF' > upm.h &&
  2134. X/*
  2135. X
  2136. Xupm.h - common data for upm.
  2137. X
  2138. X(C) MCMXC - Nick Sayer - All rights reserved.
  2139. X
  2140. X*/
  2141. X
  2142. X#include <stdio.h>
  2143. X#include "z80.h"
  2144. Xextern char *sys_errlist[];
  2145. Xextern int errno;
  2146. X
  2147. Xextern FILE *disks[16],*devices[5]; /* These are FILEs for CP/M devices */
  2148. X
  2149. Xextern WORD diskbufs[16]; /* These are pointers to disk paramater
  2150. X                             tables. See sel_dsk() */
  2151. X
  2152. X/* Which devices[] go to which physical devices? */
  2153. X#define F_TTY 0
  2154. X#define F_LPT 1
  2155. X#define F_PTP 2
  2156. X#define F_PTR 2
  2157. X#define F_UL1 3
  2158. X#define F_UC1 3
  2159. X#define F_UP1 3
  2160. X#define F_UR1 3
  2161. X#define F_UR2 4
  2162. X#define F_UP2 4
  2163. X
  2164. X/* Which command line args go to which physical devices? */
  2165. X#define F_TY 0
  2166. X#define F_LP 1
  2167. X#define F_PT 2
  2168. X#define F_U1 3
  2169. X#define F_U2 4
  2170. X
  2171. X/*
  2172. X
  2173. XWhen CP/M is run on a real system, the warm boot procedure reads
  2174. Xin the CCP image from disk. Of course, we don't have a real disk,
  2175. Xso the startup procedure for the emulator places the relocated
  2176. Ximage of the ccp into the following structure. Actually, the
  2177. Ximage size is 5.5K, so it incorporates BDOS as well.
  2178. X
  2179. X*/
  2180. X
  2181. X#define SIZE_CCP_IMAGE 5632
  2182. Xextern BYTE ccp_image[SIZE_CCP_IMAGE]; /* Save CCP for warm boot */
  2183. Xextern WORD ccp_start; /* ... and where to put it */
  2184. X
  2185. X/*
  2186. X
  2187. Xbios() implements the CP/M bios in C. The BIOS function to execute is
  2188. Xdetermined by ((PC&0xff)/3). This assumes the BIOS starts on an even
  2189. Xpage boundary, which in most cases is a requirement anyway. This allows
  2190. Xall sorts of silly things to happen if programs crunch up in strange
  2191. Xways, but that happens a lot with CP/M anyway. This routine takes no
  2192. Xformal arguments, and has all sorts of side effects on the Z-80
  2193. Xregister pairs and the Z-80 memory space. The return value is non-zero
  2194. Xif the EXIT BIOS entry (HALT at xx5D) is called.
  2195. X
  2196. X*/
  2197. X
  2198. Xextern char bios(); 
  2199. SHAR_EOF
  2200. $TOUCH -am 0928182090 upm.h &&
  2201. chmod 0644 upm.h ||
  2202. echo "restore of upm.h failed"
  2203. set `wc -c upm.h`;Wc_c=$1
  2204. if test "$Wc_c" != "1744"; then
  2205.     echo original size 1744, current size $Wc_c
  2206. fi
  2207. # ============= z80.c ==============
  2208. echo "x - extracting z80.c (Text)"
  2209. sed 's/^X//' << 'SHAR_EOF' > z80.c &&
  2210. X/*
  2211. X
  2212. Xz80.c - Z-80 microprocessor emulator.
  2213. X
  2214. XCopyright MCMXC - Nick Sayer - All rights reserved.
  2215. X
  2216. XSee COPYRIGHT file for details.
  2217. X
  2218. Xv0.0   - 04/08/90 - epoch
  2219. Xv0.0A0 - 04/13/90 - alpha-test.
  2220. Xv0.0A1 - 08/04/90 - alpha-test 2.
  2221. Xv0.0A2 - 09/04/90 - alpha-test 3.
  2222. X
  2223. Xglobal data types:
  2224. X
  2225. XWORD = unsigned short - i.e. an address or register pair.
  2226. XBYTE = unsigned char  - i.e. a memory location or register.
  2227. X
  2228. Xglobal data:
  2229. X
  2230. XBYTE z80_mem[65536];
  2231. XWORD AF,BC,DE,HL,SP,PC,IX,IY,IR,AF2,BC2,DE2,HL2,INT_FLAGS;
  2232. X
  2233. Xglobal routines:
  2234. X
  2235. Xz80_run();
  2236. X
  2237. X    Start running at addr. PRESUMES PC AND OTHER REGISTERS SET PROPERLY!!!
  2238. X    Returns if Z-80 executes a HALT. Returns with PC set to address of HALT
  2239. X    instruction.
  2240. X
  2241. Xz80_instr();
  2242. X
  2243. X    Execute a single instruction.
  2244. X
  2245. Xwrport(addr,data);
  2246. XBYTE addr,data;
  2247. X
  2248. XBYTE rdport(addr);
  2249. XBYTE addr;
  2250. X
  2251. X    These routines are called by the Z-80 when it wants to read or write
  2252. X    to the port-space.
  2253. X
  2254. Xchar INT,NMI,RESET;
  2255. X
  2256. X    Each of these starts at 0. If some event makes any of these true, the
  2257. X    event each represents will take place. Think of them as the coresponding
  2258. X    wires that go into the CPU, except that in the real CPU these wires are
  2259. X    inverse logic.
  2260. X
  2261. XBYTE int_read();
  2262. X
  2263. X    This routine called on an interrupt. It should return the proper
  2264. X    interrupt acknowledgement cycle data.
  2265. X
  2266. XKNOWN "FEATURES":
  2267. X
  2268. X    This actually simulates a MOSTEK MK 3880. Whether or not this
  2269. X    device differs from the Zilog product, I don't know. But I
  2270. X    doubt it.
  2271. X
  2272. X    If you single-step using z80_instr(), memory refresh, interrupt
  2273. X    checking, and similar housekeeping will NOT take place.
  2274. X
  2275. X    If the processor is in interrupt mode 0, the int_read()
  2276. X        value MUST be an RST instruction.
  2277. X
  2278. X    Undefined opcode sequences WILL have truely bizarre and twisted
  2279. X    results. Count on it. Especially undefined DD/FD operations.
  2280. X
  2281. X    "Interrupting devices" at this time can't tell when an interrupt
  2282. X    service routine is finished. Normally they monitor the bus
  2283. X    waiting for a RETI instruction. There's no way to do that with
  2284. X    this code yet.
  2285. X
  2286. X*/
  2287. X
  2288. X#include "z80.h"
  2289. X
  2290. XBYTE real_z80_mem[65536];
  2291. Xchar STOP_FLAG; /* hack to stop us on HALT */
  2292. Xchar INT=0,NMI=0,RESET=0;
  2293. XWORD AF,BC,DE,HL,PC,SP,IX,IY,IR,AF2,BC2,DE2,HL2,INT_FLAGS;
  2294. Xint TRAPval = -1, lastPC = -1;
  2295. X
  2296. Xz80_run()
  2297. X{
  2298. X  STOP_FLAG=0;
  2299. X  do
  2300. X  {
  2301. X
  2302. X/* do an instruction */
  2303. X
  2304. X    if (PC == TRAPval) {
  2305. X      printf("\n\rTrapping at 0x%04x (last=0x%04x)\n\r",PC,lastPC);
  2306. X      debugit();
  2307. X    }
  2308. X    lastPC = PC;
  2309. X    z80_instr();
  2310. X
  2311. X/* If we did an EI instruction before last, set both IFFs */
  2312. X
  2313. X  if (INT_FLAGS&IFTMP)
  2314. X  {
  2315. X    INT_FLAGS-=0x10;
  2316. X    if (!(INT_FLAGS&IFTMP))
  2317. X      INT_FLAGS|=IFF1|IFF2;
  2318. X  }
  2319. X
  2320. X/* If an interrupt is pending and they're enabled, do it */
  2321. X
  2322. X  if (INT && INT_FLAGS&IFF1)
  2323. X  {
  2324. X    register WORD operand;
  2325. X
  2326. X    INT_FLAGS&=~(IFF1|IFF2);
  2327. X    push(PC);
  2328. X    switch (INT_FLAGS&IM_STAT)
  2329. X    {
  2330. X      case 0:PC=int_read()&0x38; /* DANGEROUSLY assumes an RST op... */
  2331. X      break;
  2332. X      case 1:PC=0x38; int_read(); /* we have to fetch, then spike it */
  2333. X      break;
  2334. X      case 2:operand=(IR&0xff80)|(int_read()&0xfe);
  2335. X         PC=z80_mem(operand)|(z80_mem(operand+1)<<8);
  2336. X      break;
  2337. X    }
  2338. X    INT=0;
  2339. X  }
  2340. X
  2341. X/* If an NMI is pending, do it */
  2342. X
  2343. X  if (NMI)
  2344. X  {
  2345. X    INT_FLAGS&=~IFF1;
  2346. X    push(PC);
  2347. X    PC=0x66;
  2348. X    NMI=0;
  2349. X  }
  2350. X
  2351. X/* if a RESET is pending, that has absolute priority */
  2352. X
  2353. X  if (RESET)
  2354. X  {
  2355. X    INT=0; NMI=0; RESET=0; INT_FLAGS=0; PC=0;
  2356. X  }
  2357. X
  2358. X/* Now do a "refresh" cycle (really just increment low 7 bits of IR) */
  2359. X
  2360. X  IR=(IR&0xff00)|((IR+1)&0x7f);
  2361. SHAR_EOF
  2362. echo "End of  part 1"
  2363. echo "File z80.c is continued in part 2"
  2364. echo "2" > shar3_seq_.tmp
  2365. exit 0
  2366.  
  2367. -- 
  2368. Nick Sayer               | Disclaimer: "Don't try this at home, | RIP: Mel Blanc
  2369. mrapple@quack.sac.ca.us  | kids. This should only be done by    |   1908-1989
  2370. N6QQQ  [44.2.1.17]       | trained, professional idiots."       |  May he never
  2371. 209-952-5347 (Telebit)   |                     --Plucky Duck    |  be silenced.
  2372.  
  2373.